/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
// -*- mode: c++ -*-
/** 
 * \file
 * \brief Simulator Control Object - interface to simulator provoding funcs such as insert new object - header.
 * \author Antti Maula <antti.maula@tkk.fi>
 */
#ifndef _FSRSIM_SIMCTRLOBJECT_H_
#define _FSRSIM_SIMCTRLOBJECT_H_

#include "Object.h"
#include "Shapes.h"
#include "sync.hpp"
#include "thread.hpp"
#include "gimi.h"
#include <set>
#include "UnitServer.hpp"


/// A block of ah-so-useful forward-declarations
/*namespace MaCI {
  namespace MaCICtrl {
    class CMaCICtrlServer;
  }
}
namespace gimi {
  class GIMI;
  }*/

struct SSimObjectConstructionRecipe
{
  SSimObjectConstructionRecipe(const MaCI::Unit::EUnitType &aType = MaCI::Unit::KUnitTypeUnknown,
                               const std::string &aImplementation = "",
                               const std::string &aInstance = "",
                               const MaCI::Unit::TUnitPose &aPose = MaCI::Unit::TUnitPose(),
                               const uint32_t &aActiveId = 0) 
    : type(aType),
      implementation(aImplementation),
      instance(aInstance),
      pose(aPose),
      active_id(aActiveId) {}
  MaCI::Unit::EUnitType type;
  std::string implementation;
  std::string instance;
  MaCI::Unit::TUnitPose pose;
  unsigned int active_id;
};

typedef std::list<SSimObjectConstructionRecipe> TSimObjectConstructionRecipeArray;


/** SimCtrlObject - for controlling simulator.
 * 
 * Object which only exists to provide an interface for simulator actions.
 */
class CSimCtrlObject : private gim::CSync, public CObject, private gim::CThread
{
public:
  CSimCtrlObject(CWorld *World, const std::string &aMaCIGroup);    
  ~CSimCtrlObject();
  
  void Update(float StepSize);
  
  void OnCollision(CPrimitive *primitive, int numc, dContact *contacts, CPrimitive *primitive2);
  
  void Draw();
  
  void Activate();
  
  
  /** Construct a CSimCtrlObject instance from XML.
   *
   * @param[in] world         Pointer to assigned world
   * @param[in] node          Pointer to XML node to start reading from.
   * @return                  Returns pointer which should have been added to World ;)
   */
  static CObject* LoadMLMA(CWorld *world, xmlNode *node);
  
private:
  int ThreadFunction(int aThreadNumber);
  void ProcessCommand(const MaCI::Unit::TCommand *aCommand,
                      const MaCI::Unit::TUnitId *aUnitId,
                      const MaCI::Unit::TUnitPose *aUnitPose,
                      const MaCI::SMessageSource &aMessageSource);
  void ConstructSimRecipe(const SSimObjectConstructionRecipe &aRecipe);
  void ConstructPendingSimRecipes(void);

private:
  std::string iMaCIGroup;
  std::set<CObject *> iObjectArray;
  gimi::GIMI *iGIMIPtr;
  unsigned int iGIMIBufferId;

  MaCI::MaCICtrl::CMaCICtrlServer *iMaCICtrlServer;
  MaCI::Unit::CUnitServer *iUnitServer;

  std::list<CObject *> iManagedObjects; ///< Objects which are managed by this module.
  TSimObjectConstructionRecipeArray iSimObjectConstructionRecipeArray;

private:
  static volatile bool iSimCtrlObjectActive;

};

#endif
